package com.gitee.context;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import com.google.common.collect.Maps;

/**
 * Spring 上下文
 * 
 * @author 赵炎
 * @version [V1.00, 2019年1月14日]
 * @since V1.00
 */
@Component
public class ApplicationContextHolder implements ApplicationContextAware
{
    private static final Logger LOG = LoggerFactory.getLogger(ApplicationContextHolder.class);
    /**
     * context spring上下文
     */
    private static ApplicationContext applicationContext;
    
    /**
     * serviceFactory service工厂
     */
    private static final Map<String, Object> serviceFactory = Maps.newHashMap();
    
    @SuppressWarnings("static-access")
    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException
    {
        this.applicationContext = context;
    }
    
    public static ApplicationContext getApplicationContext()
    {
        return applicationContext;
    }
    /**
     * 根据类获取Bean对象
     * 
     * @param t
     * @return
     */
    public static <T> T getBean(Class<T> t)
    {
        if (LOG.isDebugEnabled())
        {
            LOG.debug("获取Bean：{}", t);
        }
        return applicationContext.getBean(t);
    }
    
    /**
     * 根据类名获取对象
     * 
     * @param name
     * @return
     */
    public static Object getBean(String name)
    {
        if (LOG.isDebugEnabled())
        {
            LOG.debug("获取Bean：{}", name);
        }
        return applicationContext.getBean(name);
    }
    
    /**
     * 获取Bean集合
     * 
     * @param t
     * @return
     */
    public static <T> Map<String, T> getBeanOfType(Class<T> t)
    {
        if (LOG.isDebugEnabled())
        {
            LOG.debug("获取Bean：{}", t);
        }
        return applicationContext.getBeansOfType(t);
    }
    
    /** 
     * 获取Service
     * @param clazz 类
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getService(Class<T> clazz)
    {
        // 类名
        String clazzName = clazz.getName();
        // 
        T v = (T)serviceFactory.get(clazzName);
        if (v == null) 
        {
            // 同步类
            synchronized (clazzName)
            {
                v = (T)serviceFactory.get(clazzName);
                if (v == null)
                {
                    LOG.info("*** Autowire {} ***", clazzName);
                    // 获取Service
                    v = ApplicationContextHolder.getBean(clazz);
                }
                LOG.info("*** {} Autowired ***", clazzName);
                // 写入缓存
                serviceFactory.put(clazzName, v);
            }
        }
        return v;
    }
}
